import json
import logging
import time
import re
import fitz
import jieba
import traceback
from datetime import datetime
from pathlib import Path

# 配置日志
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - [%(filename)s:%(lineno)d] - %(message)s',
    handlers=[
        logging.StreamHandler(),
        logging.FileHandler('contract_analysis.log', encoding='utf-8')
    ]
)
logger = logging.getLogger(__name__)

class ContractAnalyzer:
    def __init__(self):
        """初始化合同分析器"""
        self.logger = logging.getLogger(__name__)
        self.logger.info("合同分析器初始化成功")
        
        # 添加合同相关词典
        contract_words = [
            "合同编号", "合同名称", "合同类型", "签订日期", "生效日期",
            "到期日期", "合同金额", "甲方", "乙方", "联系人", "地址",
            "电话", "条款", "付款方式", "特殊约定"
        ]
        for word in contract_words:
            jieba.add_word(word)
        
        # 编译正则表达式模式
        self.patterns = {
            "合同编号": [
                r"合同编号[：:]\s*([A-Za-z0-9-]+)",
                r"编号[：:]\s*([A-Za-z0-9-]+)"
            ],
            "合同名称": [
                r"合同名称[：:]\s*([^\n]+)",
                r"^(.*?合同)[\s\n]"
            ],
            "合同类型": [
                r"合同类型[：:]\s*([^\n]+)",
                r"本(.*?合同)由"
            ],
            "申请日期": [
                r"申请日期[：:]\s*(\d{4}年\d{1,2}月\d{1,2}日)",
                r"申请日期[：:]\s*(\d{4}[-/]\d{1,2}[-/]\d{1,2})"
            ],
            "附件上传": [
                r"附件[：:]\s*([^\n]+\.pdf)",
                r"附件上传[：:]\s*([^\n]+\.pdf)"
            ],
            "签订日期": [
                r"签订日期[：:]\s*(\d{4}年\d{1,2}月\d{1,2}日)",
                r"签订日期[：:]\s*(\d{4}[-/]\d{1,2}[-/]\d{1,2})"
            ],
            "甲方名称": [
                r"甲方.*?名称[：:]\s*(\S+?(?:公司|单位|企业))",
                r"甲方[：:]\s*(\S+?(?:公司|单位|企业))"
            ],
            "甲方地址": [
                r"甲方.*?地址[：:]\s*([^\n]+)",
                r"甲方.*?住所[：:]\s*([^\n]+)"
            ],
            "甲方法定代表人": [
                r"甲方.*?法定代表人[：:]\s*([^\n]+)",
                r"甲方.*?代表人[：:]\s*([^\n]+)"
            ],
            "甲方联系方式": [
                r"甲方.*?联系方式[：:]\s*([^\n]+)",
                r"甲方.*?电话[：:]\s*([^\n]+)"
            ],
            "乙方名称": [
                r"乙方.*?名称[：:]\s*(\S+?(?:公司|单位|企业))",
                r"乙方[：:]\s*(\S+?(?:公司|单位|企业))"
            ],
            "乙方地址": [
                r"乙方.*?地址[：:]\s*([^\n]+)",
                r"乙方.*?住所[：:]\s*([^\n]+)"
            ],
            "乙方法定代表人": [
                r"乙方.*?法定代表人[：:]\s*([^\n]+)",
                r"乙方.*?代表人[：:]\s*([^\n]+)"
            ],
            "乙方联系方式": [
                r"乙方.*?联系方式[：:]\s*([^\n]+)",
                r"乙方.*?电话[：:]\s*([^\n]+)"
            ],
            "收款金额小写": [
                r"金额[：:]\s*[¥￥]\s*([\d,]+\.?\d*)",
                r"总价[：:]\s*[¥￥]\s*([\d,]+\.?\d*)",
                r"[¥￥]\s*([\d,]+\.?\d*)\s*元"
            ],
            "收款金额大写": [
                r"[（(](人民币)?([^）)]+?整)[）)]",
                r"大写[：:]\s*([^：\n]+?整)"
            ],
            "税率": [
                r"税率[：:]\s*(\d+(?:\.\d+)?%)",
                r"税率为?\s*(\d+(?:\.\d+)?%)"
            ],
            "乙方收款账号": [
                r"收款账号[：:]\s*([^\n]+)",
                r"银行账号[：:]\s*([^\n]+)",
                r"账号[：:]\s*([^\n]+)"
            ]
        }
        
    def process_file(self, file_path: str = "backend/automation/test_contract.txt") -> dict:
        """
        处理合同文件并分析内容
        Args:
            file_path: 合同文件路径，默认为test_contract.txt
        Returns:
            dict: 分析结果
        """
        try:
            start_time = time.time()
            
            # 读取文件内容
            self.logger.info(f"开始读取文件: {file_path}")
            with open(file_path, 'r', encoding='utf-8') as f:
                text_content = f.read()
            
            if not text_content:
                raise ValueError("文件内容为空")
            
            # 分析合同内容
            self.logger.info("开始分析合同内容...")
            result = self._analyze_contract(text_content)
            
            # 计算执行时间
            end_time = time.time()
            total_time = end_time - start_time
            
            self.logger.info(f"处理完成，总耗时: {total_time:.2f}秒")
            
            return {
                "status": "success",
                "result": result,
                "execution_time": {
                    "total": total_time
                }
            }
            
        except FileNotFoundError as e:
            error_info = self._get_error_info()
            self.logger.error(f"文件不存在: {file_path}\n{error_info}")
            return {
                "status": "error",
                "error_type": "FileNotFoundError",
                "message": f"文件不存在: {file_path}",
                "traceback": error_info
            }
        except ValueError as e:
            error_info = self._get_error_info()
            self.logger.error(f"值错误: {str(e)}\n{error_info}")
            return {
                "status": "error",
                "error_type": "ValueError",
                "message": str(e),
                "traceback": error_info
            }
        except Exception as e:
            error_info = self._get_error_info()
            self.logger.error(f"处理文件时发生错误: {str(e)}\n{error_info}")
            return {
                "status": "error",
                "error_type": type(e).__name__,
                "message": str(e),
                "traceback": error_info
            }

    def _get_error_info(self) -> str:
        """获取详细的错误信息，包括堆栈跟踪"""
        return traceback.format_exc()

    def _extract_pdf_text(self, file_path: str) -> str:
        """
        从PDF文件中提取文本
        Args:
            file_path: PDF文件路径
        Returns:
            str: 提取的文本内容
        """
        try:
            self.logger.info(f"开始读取PDF文件: {file_path}")
            start_time = time.time()
            
            # 打开PDF文件
            doc = fitz.open(file_path)
            text = ""
            
            # 遍历每一页并提取文本
            for page_num in range(len(doc)):
                page = doc[page_num]
                text += page.get_text()
            
            # 关闭PDF文件
            doc.close()
            
            if not text:
                raise Exception("未能从PDF中提取到文本")
                
            self.logger.info(f"PDF文本提取成功，长度: {len(text)} 字符")
            self.logger.info(f"文本提取耗时: {time.time() - start_time:.2f}秒")
            
            return text
            
        except Exception as e:
            self.logger.error(f"提取PDF文本时发生错误: {str(e)}")
            raise Exception(f"PDF文本提取失败: {str(e)}")
            
    def _analyze_contract(self, content: str) -> dict:
        """
        分析合同内容
        Args:
            content: 合同文本内容
        Returns:
            dict: 分析结果
        """
        try:
            self.logger.info("开始分析合同内容...")
            start_time = time.time()
            
            if not content or len(content.strip()) == 0:
                raise ValueError("合同内容为空")
            
            self.logger.info(f"合同内容长度: {len(content)} 字符")
            
            # 使用jieba分词
            words = list(jieba.cut(content))
            self.logger.info(f"分词完成，共{len(words)}个词")
            
            # 初始化结果
            result = {
                "合同编号": None,
                "合同名称": None,
                "合同类型": None,
                "申请日期": None,
                "附件上传": None,
                "签订日期": None,
                "甲方信息": {
                    "名称": None,
                    "地址": None,
                    "法定代表人": None,
                    "联系方式": None
                },
                "乙方信息": {
                    "名称": None,
                    "地址": None,
                    "法定代表人": None,
                    "联系方式": None
                },
                "财务信息": {
                    "收款金额（小写）": None,
                    "收款金额（大写）": None,
                    "税率": None,
                    "乙方收款账号": None
                }
            }
            
            # 使用正则表达式提取信息
            for field, patterns in self.patterns.items():
                for pattern in patterns:
                    matches = re.findall(pattern, content)
                    if matches:
                        value = matches[0].strip()
                        if field.startswith("甲方"):
                            key = field.replace("甲方", "")
                            result["甲方信息"][key] = value
                        elif field.startswith("乙方"):
                            key = field.replace("乙方", "")
                            result["乙方信息"][key] = value
                        elif field.startswith("收款金额小写"):
                            result["财务信息"]["收款金额（小写）"] = f"¥{value}"
                        elif field.startswith("收款金额大写"):
                            result["财务信息"]["收款金额（大写）"] = f"人民币{value}"
                        elif field == "税率":
                            result["财务信息"]["税率"] = value
                        elif field == "乙方收款账号":
                            result["财务信息"]["乙方收款账号"] = value
                        else:
                            result[field] = value
                        break
            
            self.logger.info(f"合同分析成功，用时: {time.time() - start_time:.2f} 秒")
            return result
            
        except Exception as e:
            self.logger.error(f"分析合同内容时发生错误: {str(e)}")
            raise Exception(f"分析合同内容失败: {str(e)}")
            
    def _extract_terms(self, content: str, term_type: str) -> list:
        """
        提取合同条款
        Args:
            content: 合同文本内容
            term_type: 条款类型
        Returns:
            list: 条款列表
        """
        terms = []
        # 匹配条款段落
        pattern = f"{term_type}：(.*?)(?=(?:主要条款|付款方式|特殊约定)：|$)"
        matches = re.findall(pattern, content, re.DOTALL)
        if matches:
            # 分割成单独的条款
            for match in matches:
                # 移除序号和多余的空白字符
                items = re.split(r"\d+\.\s*", match.strip())
                # 过滤空字符串并清理每个条款
                terms.extend([item.strip() for item in items if item.strip()])
        return terms

def test_analysis():
    """测试合同分析功能"""
    try:
        # 初始化分析器
        analyzer = ContractAnalyzer()
        
        # 处理文件
        result = analyzer.process_file()
        
        # 打印结果
        print("\n执行结果:")
        if isinstance(result, dict):
            if result["status"] == "error":
                print(f"状态: 失败")
                print(f"错误类型: {result.get('error_type', '未知')}")
                print(f"错误信息: {result['message']}")
                if result.get('traceback'):
                    print("\n详细错误信息:")
                    print(result['traceback'])
                if "execution_time" in result:
                    print_execution_time(result["execution_time"])
            else:
                print(f"状态: 成功\n")
                print("分析结果:")
                print(json.dumps(result["result"], ensure_ascii=False, indent=2))
                print()
                if "execution_time" in result:
                    print_execution_time(result["execution_time"])
        else:
            print(f"未知的返回结果格式: {result}")
            
    except Exception as e:
        print(f"\n执行过程中发生错误:")
        print(traceback.format_exc())

def print_execution_time(exec_time):
    """打印执行时间统计"""
    if isinstance(exec_time, dict):
        print(f"\n执行时间统计:")
        for key, value in exec_time.items():
            print(f"{key}: {value:.2f}秒")
    else:
        print(f"\n总耗时: {exec_time:.2f}秒")

if __name__ == "__main__":
    # 配置日志
    logging.basicConfig(
        level=logging.INFO,
        format='%(asctime)s - %(levelname)s - %(message)s'
    )
    
    # 测试分析功能
    test_analysis() 